package org.study.bookmanager.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SecureDigestAlgorithm;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.study.bookmanager.entity.Roles;
import org.study.bookmanager.entity.Users;
import org.study.bookmanager.repo.UsersRespository;

import javax.crypto.SecretKey;
import java.util.*;

@Data
@Component
@Slf4j
@ConfigurationProperties(prefix = "jwt")
public class JwtUtils {

    private static String header;
    private static long  expire;
    private static String secret;
    private static String issuer;

    @Resource
    private UsersRespository usersRespository;

    private String Header;
    private long Expire;
    private String Secret;
    private String Issuer;

    private static UsersRespository staticRepo;

    @PostConstruct
    public void init() {
        JwtUtils.staticRepo=usersRespository;
        header=Header;
        expire=Expire;
        secret=Secret;
        issuer=Issuer;
    }

    private static final HashSet<String> blackList = new HashSet<>();

    public static Map<String,Object> createClaims(String userName) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("userName", userName);
        Users user=staticRepo.findRoleByuserName(userName);
        if(user!=null) {
            Roles.Authority role=user.getRole().getRoleName();
            claims.put("role", Objects.requireNonNullElse(role, Roles.Authority.GUEST));
        }else{
            claims.put("role", Roles.Authority.GUEST);
        }
        return claims;
    }
    /**
     * 生成jwt
     * 使用Hs256算法，私钥使用固定密钥
     * @param claims     设置的信息
     * @return
     */
    public static String createJWT(Map<String, Object> claims){
        //指定加密算法
        SecureDigestAlgorithm<SecretKey, SecretKey> algorithm = Jwts.SIG.HS256;
        //生成JWT的时间
        long expMillis = System.currentTimeMillis()+expire;
        Date exp = new Date(expMillis);
        //密钥实例
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());

        return Jwts.builder()
                .signWith(key, algorithm) //设置签名使用的签名算法和签名使用的秘钥
                //如果有私有声明，一点要先设置这个自己创建的私有的声明，这个是给builder的claims赋值，一旦卸载标准的声明赋值之后，就是覆盖了那些标准的声明的
                .expiration(exp)
                .claims(claims) //设置自定义负载信息
                .issuer(issuer)
                .compact();
    }


    /**
     * 解析jwt
     * @param token
     * @return
     */
    public static Jws<Claims> parseJWT(String token){
        //密钥实例
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());

        return Jwts.parser()
                .verifyWith(key)  //设置签名的密钥
                .build()
                .parseSignedClaims(token);
    }


    /**
     * 获取合法claims
     * @param token
     * @return
     */
    public static Claims getClaims(String token) {
        Claims claims=parseJWT(token).getPayload();
        if(claims==null||isTokenExpired(claims)){
            return null;
        }
        return claims;
    }

    /**
     * 从Claim获取Role
     * @param claims
     * @return
     */
    public static Roles.Authority getRoleFromClaims(Claims claims){
        Roles.Authority role = null;
        if (claims != null) {
            role=claims.get("role", Roles.Authority.class);
        }
        return role;
    }

    /**
     * 获取Role
     * @param token
     * @return
     */
    public static Roles.Authority getRole(String token){
        Claims claims=getClaims(token);
        return getRoleFromClaims(claims);
    }

    public static String getUserName(String token){
        Claims claims=getClaims(token);
        log.error("claims:{}",claims);
        if(claims!=null){
            log.error("userName 1:{}",claims.get("userName",String.class));
            return claims.get("userName",String.class);
        }
        return null;
    }

    /**
     * 获取User
     * @param token
     * @return
     */
    public static Users getUser(String token) {
        Claims claims = getClaims(token);
        if (claims != null) {
            Users user = staticRepo.findByuserName(claims.get("userName", String.class));
            if(user!=null){
                return user;
            }
        }
        return null;
    }

    /**
     * 判断token是否过期
     * @param claims
     * @return
     */
    public static boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }

//    public static Claims validateToken(String token) {
//        try {
//            return Jwts.parser().setSigningKey(secret)
//        } catch (ExpiredJwtException e) {
//            // JWT过期
//            e.printStackTrace();
//        } catch (UnsupportedJwtException e) {
//            // 不支持的JWT
//            e.printStackTrace();
//        } catch (MalformedJwtException e) {
//            // JWT格式错误
//            e.printStackTrace();
//        } catch (SignatureException e) {
//            // JWT签名不一致
//            e.printStackTrace();
//        } catch (IllegalArgumentException e) {
//            // JWT为空或格式错误
//            e.printStackTrace();
//        }
//        return null;
//    }
}
